#ifndef OBJC_SCOPE_H
#define OBJC_SCOPE_H

#include <sobjc-commons/st.h>
#include "node.h"
#include "class.h"

typedef struct objc_scope       *objc_scope_t;
typedef struct objc_scope_entry *objc_scope_entry_t;

typedef void (*objc_scope_iter_stret_f)(char *, void *);

enum OBJC_NAME_TYPE {
  OBJC_COMPILER_BUILTIN,
  OBJC_TYPE_NAME,
  OBJC_STRUCT_NAME,
  OBJC_UNION_NAME,
  OBJC_ENUM_NAME,
  OBJC_CLASS_NAME,
  OBJC_VAR_NAME,
  OBJC_SELF
};

struct objc_scope {
  st_table_t type_table;
  st_table_t struct_table;
  st_table_t stret_table;
  objc_class_t cls;
  struct objc_scope *parent;
};

struct objc_scope_entry {
  objc_scope_t sc;
  int type;
  char *name;
  char *ctype;
  union {
    struct {
      objc_node_t spcr;
      objc_node_t dclr;
      char *ctype;
    } type;
    objc_class_t cls;
  } a;
};

objc_scope_t objc_make_root_scope();
objc_scope_t objc_make_scope(objc_scope_t);
objc_scope_t objc_make_meth_def_scope(objc_scope_t);

objc_scope_t objc_scope_root_scope(objc_scope_t);

objc_scope_entry_t objc_scope_get_type(objc_scope_t, const char *);
objc_scope_entry_t objc_scope_get_struct(objc_scope_t, const char *);
objc_scope_entry_t objc_scope_get_var(objc_scope_t, const char *);
objc_class_t objc_scope_get_class(objc_scope_t);
const char *objc_scope_entry_get_ctype(objc_scope_entry_t);
void objc_scope_set_type(objc_scope_t, objc_node_t, objc_node_t, char *);
void objc_scope_set_struct(objc_scope_t, objc_node_t, char *);
objc_class_t objc_scope_set_class(objc_scope_t, objc_node_t);
void objc_scope_set_alias_for_class(objc_scope_t, const char *, const char *);

void objc_scope_set_var(objc_scope_t, objc_node_t, objc_node_t, char *);

void objc_scope_init_method_definition();
void objc_scope_register_stret_type(objc_scope_t, char *);
void objc_scope_iter_stret(objc_scope_t, objc_scope_iter_stret_f, void *);

#endif /* OBJC_SCOPE_H */
